/*
 *  Copyright 2010 Massimiliano Mazzarolo
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *  
 *     http://www.apache.org/licenses/LICENSE-2.0
 *        
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License. 
 */
package grails.coherence.support

import grails.coherence.FilterBuilder

import com.tangosol.util.InvocableMap.EntryProcessor
import com.tangosol.util.InvocableMap.EntryAggregator
import com.tangosol.net.NamedCache

/**
 * Simple Coherence support for Grails application. 
 * 
 * @author Massimiliano Mazzarolo
 * @since 0.1
 */
class CoherenceSupport {
	
	
	/**
	 * Register a {@link com.tangosol.coherence.spring.SpringAwareCacheFactory} cache factory instance
	 * on Spring context. 
	 */
	static doWithSpring = {		
		if (application.config.coherence.enabled) {			
			// Register a SpringAwareFactoryBean if no ConfigurableCacheFactory were already register		
			def coherenceCfg = application.config.coherence.config ?: "coherence-cache-config.xml"
			cacheFactory(com.tangosol.coherence.spring.SpringAwareCacheFactory, coherenceCfg)				
		}
	}
	
	/**
	 * Register additional methods on NamedCache that leverages DSL filter syntax. 
	 */
	static registerMethods =  {
		
		/*
		 * NamedCache.entrySet {closure}
		 */
		NamedCache.metaClass.entrySet = {Closure closure ->
			def fb = new FilterBuilder()
			closure.delegate = fb
			closure.resolveStrategy = Closure.DELEGATE_FIRST
			closure()
			return delegate.entrySet(fb.filter)
		}
		
		/*
		 * NamedCache.entrySet(comparator) {closure}
		 */
		NamedCache.metaClass.entrySet = {Comparator comp, Closure closure ->
			def fb = new FilterBuilder()
			closure.delegate = fb
			closure.resolveStrategy = Closure.DELEGATE_FIRST
			closure()
			return delegate.entrySet(fb.filter, comp)
		}
		
		/*
		 * NamedCache.values() {closure}
		 */
		NamedCache.metaClass.values = {Closure closure ->
			return delegate.entrySet(closure)*.value
		}
		
		/*
		 * NamedCache.values(comparator) {closure}
		 */
		NamedCache.metaClass.values = {Comparator comp, Closure closure ->
			return delegate.entrySet(comp, closure)*.value
		}
		
		/*
		 * NamedCache.keySet {closure}
		 */
		NamedCache.metaClass.keySet = {Closure closure ->
			def fb = new FilterBuilder()
			closure.delegate = fb
			closure.resolveStrategy = Closure.DELEGATE_FIRST
			closure()
			return delegate.keySet(fb.filter)
		}
		
		/*
		 * NamedCache.invokeAll(processor) {closure}
		 */
		NamedCache.metaClass.invokeAll = {EntryProcessor processor, Closure closure ->
			def fb = new FilterBuilder()
			closure.delegate = fb
			closure.resolveStrategy = Closure.DELEGATE_FIRST
			closure()
			return delegate.invokeAll(fb.filter, processor)
		}
		
		/*
		 * NamedCache.aggregate(aggregator) {closure}
		 */
		NamedCache.metaClass.aggregate = {EntryAggregator aggregator, Closure closure ->
			def fb = new FilterBuilder()
			closure.delegate = fb
			closure.resolveStrategy = Closure.DELEGATE_FIRST
			closure()
			return delegate.aggregate(fb.filter, aggregator)
		}				
	}
}